package com.example.base.mvi

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.cachedIn
import com.example.base.entity.Res
import com.example.base.net.ShopApiService
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File
import kotlin.math.log

abstract class BaseViewModel<UiIntent:IUiIntent>:ViewModel() {
    //创建一个channel接收所有的请求操作
    val channel = Channel<UiIntent>()
    //创建一个state用来接收所有请求的状态
    private var _state = MutableStateFlow<UiState>(UiState.onLoading)
    //对外暴露一个state  不可变的
    val uiState:StateFlow<UiState>
        get() = _state
    //封装一个公共方法  用来进行页面的发送事件
    fun sendIntent(uiIntent: UiIntent){
        viewModelScope.launch {
            channel.send(uiIntent)
        }
    }
    //页面接收到返回的值进行处理
    init {
        viewModelScope.launch {
            channel.receiveAsFlow().collect{
                //需要根据实际业务进行处理  抽象方法
                handleIntent(it)
            }
        }
    }

    abstract fun handleIntent(it: UiIntent)

    //封装网络请求方法
    fun <T> httpRequest(request:Flow<Res<T>>,type: HttpType=HttpType.DEFAULT){
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.d("zll", "httpRequest:操作失败:${it.message} ")
                }.collect{
                    if(it.code==200){
                        _state.value = UiState.onSuccess(it.data,type)
                    }else{
                        _state.value = UiState.onError(it.msg?:it.message)
                    }
                }
        }
    }
    //封装分页的网络请求
    fun <T:Any> pageRequest(pagingSource:()->PagingSource<Int,T>,type: HttpType=HttpType.DEFAULT){
        val pager =
            Pager(config = PagingConfig(pageSize = 5), pagingSourceFactory = { pagingSource() })
                .flow
                .cachedIn(viewModelScope)//进行缓存 减少加载
        viewModelScope.launch {
            pager.flowOn(Dispatchers.IO)
                .catch {
                    Log.d("zll", "pageRequest:操作失败:${it.message} ")
                }
                .collect{
                    _state.value = UiState.onSuccess(it,type)
                }
        }
    }
    //封装数据库请求
    fun <T> roomRequest(requset:Flow<T>,type: HttpType=HttpType.DEFAULT){
        viewModelScope.launch {
            requset.flowOn(Dispatchers.IO)
                .catch {
                    Log.d("zll", "roomRequest:数据库操作失败:${it.message}")
                }.collect{
                    if(it!=null){
                        _state.value = UiState.onSuccess(it,type)
                    }else{
                        _state.value = UiState.onError("数据库操作失败")
                    }
                }
        }
    }

    fun toBody(item:Any):RequestBody{
        val json = Gson().toJson(item)
        return RequestBody.create("application/json;charset=utf-8".toMediaType(),json)
    }
    fun toPart(path:String,fileName:String):MultipartBody.Part{
        val body = RequestBody.create("multipart/form-data".toMediaTypeOrNull(), File(path))
        val part = MultipartBody.Part.createFormData("file",fileName,body)
        return part
    }


}